/*
    Copyright (C) 2012  Collombet

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "dynamicarray.h"

void dynamicArray_create(DynamicArray** dynamicArray)
{
    (*dynamicArray) = (DynamicArray*) malloc(sizeof(DynamicArray));
}

void dynamicArray_initialize(DynamicArray* dynamicArray)
{
    dynamicArray->array = (void**) malloc(sizeof(void*));
    dynamicArray->count = 0;
    dynamicArray->allocated = 1;
}

void dynamicArray_initializeCopy(DynamicArray* dynamicArray, const DynamicArray* source)
{
    dynamicArray_clear(dynamicArray);
}

void dynamicArray_copy(DynamicArray* dynamicArray, const DynamicArray* source)
{
    int i;
    dynamicArray->count = source->count;
    for(i = 0; i < dynamicArray->count; i++)
    {
        dynamicArray_inserLast(dynamicArray,source->array[i]);
    }
}

void dynamicArray_clear(DynamicArray* dynamicArray)
{
    if(dynamicArray != NULL)
        free(dynamicArray->array);
    dynamicArray->array = NULL;
    dynamicArray->count = 0;
    dynamicArray->allocated = 1;
}

void dynamicArray_destroy(DynamicArray** dynamicArray)
{
    dynamicArray_clear((*dynamicArray));
    free((*dynamicArray));
    (*dynamicArray) = NULL;
}

void dynamicArray_inserFirst(DynamicArray* dynamicArray, void* value)
{
    dynamicArray_inserAt(dynamicArray,value,0);
}

void dynamicArray_inserLast(DynamicArray* dynamicArray, void* value)
{
    dynamicArray_inserAt(dynamicArray,value,dynamicArray->count);
}

int dynamicArray_inserAt(DynamicArray* dynamicArray, void* value, int index)
{
    if((index >= 0) && (index <= dynamicArray->count))
    {
        int i;
        if(dynamicArray->count  == dynamicArray->allocated)
        {
            dynamicArray->allocated *= 2;
            dynamicArray->array = (void**) realloc(dynamicArray->array, sizeof(void*) * dynamicArray->allocated);
        }
        for(i = dynamicArray->count; i > index; i--)
            dynamicArray->array[i] =  dynamicArray->array[i- 1];
        dynamicArray->array[index] = value;
        dynamicArray->count++;
        return 1;
    }
    else
        return 0;
}

void dynamicArray_removeLast(DynamicArray* dynamicArray)
{
    dynamicArray_removeAt(dynamicArray, dynamicArray->count - 1);
}

void dynamicArray_removeFirst(DynamicArray* dynamicArray)
{
    dynamicArray_removeAt(dynamicArray,0);
}

int dynamicArray_remove(DynamicArray* dynamicArray, void *value)
{
    int i;
    for(i = 0; i < dynamicArray->count; i++)
    {
        if(dynamicArray->array[i] == value)
        {
            dynamicArray_removeAt(dynamicArray,i);
            return i;
        }
    }
    return 0;
}

int dynamicArray_removeAt(DynamicArray* dynamicArray, const int index)
{
    if((index < dynamicArray->count) && (index >= 0))
    {
        int i;

        dynamicArray->array[index] = NULL;

        for (i = index; i < (dynamicArray->count - 1); i++)
            dynamicArray->array[i] = dynamicArray->array[i+1];

        if((dynamicArray->count - 2) == (dynamicArray->allocated / 3))
        {
            dynamicArray->allocated /= 2;
            dynamicArray->array = realloc(dynamicArray->array, sizeof(void*) * dynamicArray->allocated);
        }

        dynamicArray->count--;
        return 1;
    }
    else
        return 0;
}
